// CSmtp.h: interface for the Smtp class.
//
//////////////////////////////////////////////////////////////////////

#if !defined __CSMTP_H__
#define __CSMTP_H__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <winsock2.h>

#include <assert.h>

#pragma comment(lib, "ws2_32.lib")

#pragma warning(push)
#pragma warning(disable:4786)

#include <vector>
#include <string>

#define BUFFER_SIZE 10240      // SendData and RecvData buffers sizes
#define DELAY_IN_MS 10            // delay between send and recv functions
#define MSG_SIZE_IN_MB 5        // the maximum size of the message with all attachments

const char BOUNDARY_TEXT[] = "__MESSAGE__ID__54yg6f6h6y456345";

enum CSmtpError
{
    CSMTP_NO_ERROR = 0,
    CSMTP_WSA_STARTUP = 100, // WSAGetLastError()
    CSMTP_WSA_VER,
    CSMTP_WSA_SEND,
    CSMTP_WSA_RECV,
    CSMTP_WSA_CONNECT,
    CSMTP_WSA_GETHOSTBY_NAME_ADDR,
    CSMTP_WSA_INVALID_SOCKET,
    CSMTP_WSA_HOSTNAME,
    CSMTP_BAD_IPV4_ADDR,
    CSMTP_UNDEF_MSG_HEADER = 200,
    CSMTP_UNDEF_MAILFROM,
    CSMTP_UNDEF_SUBJECT,
    CSMTP_UNDEF_RECIPENTS,
    CSMTP_UNDEF_LOGIN,
    CSMTP_UNDEF_PASSWORD,
    CSMTP_UNDEF_RECIPENT_MAIL,
    CSMTP_COMMAND_MAIL_FROM = 300,
    CSMTP_COMMAND_EHLO,
    CSMTP_COMMAND_AUTH_LOGIN,
    CSMTP_COMMAND_DATA,
    CSMTP_COMMAND_QUIT,
    CSMTP_COMMAND_RCPT_TO,
    CSMTP_MSG_BODY_ERROR,
    CSMTP_CONNECTION_CLOSED = 400, // by server
    CSMTP_SERVER_NOT_READY, // remote server
    CSMTP_FILE_NOT_EXIST,
    CSMTP_MSG_TOO_BIG,
    CSMTP_BAD_LOGIN_PASS,
    CSMTP_UNDEF_XYZ_RESPOMSE,
    CSMTP_LACK_OF_MEMORY
};

enum CSmptXPriority
{
    XPRIORITY_HIGH = 2,
    XPRIORITY_NORMAL = 3,
    XPRIORITY_LOW = 4
};

class CSmtp  
{
public:
    CSmtp();
    virtual ~CSmtp();
    bool AddRecipient(const char *email, const char *name=NULL);
    bool AddBCCRecipient(const char *email, const char *name=NULL);
    bool AddCCRecipient(const char *email, const char *name=NULL);    
    bool AddAttachment(const char *path);   
    const unsigned int GetBCCRecipientCount();    
    const unsigned int GetCCRecipientCount();
    const unsigned int GetRecipientCount();    
    const char* const GetLocalHostIP();
    const char* const GetLocalHostName();    
    const char* const GetMessageBody();    
    const char* const GetReplyTo();
    const char* const GetMailFrom();
    const char* const GetSenderName();
    const char* const GetSubject();    
    const char* const GetXMailer();
    CSmptXPriority GetXPriority();
    CSmtpError GetLastError();
    bool Send();
    void SetMessageBody(const char*);
    void SetSubject(const char*);
    void SetSenderName(const char*);
    void SetSenderMail(const char*);
    void SetReplyTo(const char*);
    void SetXMailer(const char*);
    void SetLogin(const char*);
    void SetPassword(const char*);
    void SetXPriority(CSmptXPriority);
    void SetSMTPServer(const char* server,const unsigned short port=0);

private:    
    CSmtpError m_oError;
    char* m_pcLocalHostName;
    char* m_pcMailFrom;
    char* m_pcNameFrom;
    char* m_pcSubject;
    char* m_pcMsgBody;
    char* m_pcXMailer;
    char* m_pcReplyTo;
    char* m_pcIPAddr;
    char* m_pcLogin;
    char* m_pcPassword;
    char* m_pcSMTPSrvName;
    unsigned short m_iSMTPSrvPort;
    CSmptXPriority m_iXPriority;
    char *SendBuf;
    char *RecvBuf;



    WSADATA wsaData;
    SOCKET hSocket;

    struct Recipent
    {
        std::string Name;
        std::string Mail;
    };

    std::vector<Recipent> Recipients;
    std::vector<Recipent> CCRecipients;
    std::vector<Recipent> BCCRecipients;
    std::vector<std::string> Attachments;

    bool ReceiveData();
    bool SendData();
    bool FormatHeader(char*);
    int SmtpXYZdigits();
    SOCKET ConnectRemoteServer(const char* server, const unsigned short port=NULL);

    friend char* GetErrorText(CSmtpError);
};


#pragma warning(pop)

#endif // __CSMTP_H__